import static name.audet.samuel.javacv.jna.cxcore.*;
import static name.audet.samuel.javacv.jna.cv.*;
import static name.audet.samuel.javacv.jna.highgui.*;
import static name.audet.samuel.javacv.jna.cvaux.*;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ByteLookupTable;
import java.awt.image.ColorModel;
import java.awt.image.ConvolveOp;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DirectColorModel;
import java.awt.image.Kernel;
import java.awt.image.LookupOp;
import java.awt.image.Raster;
import java.awt.image.RescaleOp;
import java.awt.image.WritableRaster;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;

import java.awt.MediaTracker;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import com.ia.faceDetectetion.downloadMosaicImage;
import com.ia.neuralNetwork.neuralNetwork;
import com.sun.jna.Pointer;



import name.audet.samuel.javacv.CanvasFrame;
import name.audet.samuel.javacv.OpenCVFrameGrabber;
import name.audet.samuel.javacv.jna.cv;
import name.audet.samuel.javacv.jna.cv.CvHaarClassifierCascade;
import name.audet.samuel.javacv.jna.cxcore.CvArr;
import name.audet.samuel.javacv.jna.cxcore.CvMemStorage;
import name.audet.samuel.javacv.jna.cxcore.CvPoint;
import name.audet.samuel.javacv.jna.cxcore.CvRect;
import name.audet.samuel.javacv.jna.cxcore.CvScalar;
import name.audet.samuel.javacv.jna.cxcore.CvSeq;
import name.audet.samuel.javacv.jna.cxcore.IplImage;

public class Test extends JFrame {
	
	
	public static  Image loadedImage;
	public static int BINA = 400;
	private static BufferedImage image;
	final static String FICHERO_PATRONES = "/Volumes/programacion/redneuronal/patrones/PATRONESCARAS2.TXT";
	final static String FICHERO_PESOS = "PESOSCARAS.TXT";
	final static String PATH_PESOS = "/Volumes/programacion/redneuronal/pesos/";
	
	static IplImage  grayImage ;
	static Image imagen;
	static BufferedImage imagenFoto;
	
	int areaX = 0;
	int areaY = 0;
	int areaWidth = 0;
	int areaHeight = 0;
	int stateButton;
	static MouseListener l = null;
	
	static BufferedImage biSrc;
	static BufferedImage biDest;
	static BufferedImage bi; 
    static Graphics2D big; 
    static RescaleOp rescale; 
    static float scaleFactor = 1.0f ; 
    static float offset = 10 ; 
    static boolean brighten;
	boolean contrastInc; 
    
	public static neuralNetwork nn = null;
	public static downloadMosaicImage dmi = null;
	final static int ALTO_REJILLA = 20;
	final static int ANCHO_REJILLA = 20;
	
	
//	   public static BufferedImage createBufferedImages (BufferedImage im) { 
//		  
//	         biSrc = new BufferedImage ( im.getWidth () , 
//	        		 im.getHeight () , 
//	                 BufferedImage.TYPE_INT_RGB ) ; 
//
//	         big = biSrc.createGraphics () ; 
//	         big.drawImage ( im, 0 , 0 , null ) ; 
//
//	         biDest = new BufferedImage ( im.getWidth (  ) , 
//	        		 im.getHeight (  ) , 
//	                 BufferedImage.TYPE_INT_RGB ) ; 
//	         
//	         return big;
//	         
//	     } 

	     public static void changeOffSet () { 
	         if ( brighten ) { 
	             if ( offset < 255 ) 
	                offset = offset+ 5.0f ; 
	         } 
	         else { 
	             if ( offset > 0 ) 
	                offset = offset- 5.0f ; 
	         } 
	     } 

	     public void changeScaleFactor () { 
	         if ( contrastInc ) { 
	             if ( scaleFactor < 2 ) 
	                 scaleFactor = scaleFactor+ 0.1f ; 
	         } 
	         else { 
	             if ( scaleFactor > 0 ) 
	                 scaleFactor = scaleFactor- 0.1f ; 
	         } 
	     } 
	     
	     public static BufferedImage contraste( BufferedImage img,float c) {
	    	 offset = offset- 5.0f ; 
	    	 scaleFactor = scaleFactor- c ; 
	    	 rescale = new RescaleOp ( scaleFactor, offset, null ) ; 
	    	   biDest = new BufferedImage ( img.getWidth (  ) , 
	    			   img.getHeight (  ) , 
	                 BufferedImage.TYPE_INT_RGB ) ; 
	         
	         rescale.filter ( img, biDest ) ; 
	         return (img);
	     }
	     
	 
	
	public static BufferedImage scaleToSize(int nMaxWidth, int nMaxHeight,
			BufferedImage imgSrc) {
		int nHeight = imgSrc.getHeight();
		int nWidth = imgSrc.getWidth();
		double scaleX = (double) nMaxWidth / (double) nWidth;
		double scaleY = (double) nMaxHeight / (double) nHeight;
		double fScale = Math.min(scaleX, scaleY);
		return scale(fScale, imgSrc);
	}

	public static BufferedImage scale(double scale, BufferedImage srcImg) {
		if (scale == 1) {
			return srcImg;
		}
		AffineTransformOp op = new AffineTransformOp(AffineTransform
				.getScaleInstance(scale, scale), null);

		return op.filter(srcImg, null);

	}
	
	private static void filter(BufferedImageOp op) {
	    BufferedImage filteredImage = new BufferedImage(image.getWidth(), image
	        .getHeight(), image.getType());
	    op.filter(image, filteredImage);
	    image = filteredImage;
	 
	  }

	  private static void convolve(float[] elements) {
	    Kernel kernel = new Kernel(3, 3, elements);
	    ConvolveOp op = new ConvolveOp(kernel);
	    filter(op);
	  }

	  public static void blur() {
	    float weight = 1.0f / 9.0f;
	    float[] elements = new float[9];
	    for (int i = 0; i < 9; i++)
	      elements[i] = weight;
	    convolve(elements);
	  }

	  public void sharpen() {
	    float[] elements = { 0.0f, -1.0f, 0.0f, -1.0f, 5.f, -1.0f, 0.0f, -1.0f,
	        0.0f };
	    convolve(elements);
	  }
	  
	// @Override
		public void mousePressed(MouseEvent arg0) {
			arg0.consume();
			System.out.println("sldjfkldf");
			if (stateButton == 1) {
				areaX = arg0.getX();
				areaY = arg0.getY();
				
			}
		}

		// @Override
		public void mouseReleased(MouseEvent arg0) {
			arg0.consume();
			System.out.println("sldjfkldf");
			if (stateButton == 1) {
				areaWidth = arg0.getX() - areaX;
				areaHeight = arg0.getY() - areaY;
				
			}
		}

		// @Override
		public void mouseDragged(MouseEvent arg0) {
			arg0.consume();
			System.out.println("sldjfkldf");
			if (stateButton == 1) {
				areaWidth = arg0.getX() - areaX;
				areaHeight = arg0.getY() - areaY;
				
			}
		}
	
	public static boolean salvarImagen(final BufferedImage imagen,
			final String rutaFichero, final String formato) {

		// Comprobacion de parametros
		if (imagen != null && rutaFichero != null && formato != null) {

			try {
				ImageIO.write(imagen, formato, new File(rutaFichero));
				return true;
			} catch (Exception e) {
				// Fallo al guardar

				return false;
			}
		} else {
			// Fallo en los parametros
			return false;
		}
	}
	
	public static BufferedImage loadImage(String name) {
	       JLabel label = new JLabel();
           MediaTracker media = new MediaTracker(label);

           loadedImage = Toolkit.getDefaultToolkit().getImage (name);
           media.addImage(loadedImage, 23);
           
           try
           {
              media.waitForID(23);
           }
           catch (InterruptedException e)
           {
              System.out.println ("Me han interrumpido");
              System.out.println ("Puede que la imagen todavía no haya terminado de cargarse");
           }
           
           return toBufferedImage(loadedImage);
           
	  }
	
	public static BufferedImage toBufferedImage(Image image) {
		/** miramos uqe la imagen no sea ya una instancia de BufferedImage */
		if (image instanceof BufferedImage) {
			/** genial, no hay que hacer nada */
			return ((BufferedImage) image);
		} else {
			/** nos aseguramos que la imagen está totalmente cargada */
			image = new ImageIcon(image).getImage();
			/** creamos la nueva imagen */
			BufferedImage bufferedImage = new BufferedImage(image
					.getWidth(null), image.getHeight(null),
					BufferedImage.TYPE_USHORT_GRAY);
			Graphics g = bufferedImage.createGraphics();
			g.drawImage(image, 0, 0, null);
			g.dispose();
			return (bufferedImage);
		}
	}
	
	public static BufferedImage binariza(Image im) {

		BufferedImage reticula = toBufferedImage(im);

		int argb, r, bg, g;

		int colorBlanco = 0;
		int colorNegro = 0;
		int count=0;
		int ne=0;
		int ba=0;
		
		do  {
		
		for (int x = 0; x < reticula.getWidth(); x = x + 1) {
			for (int y = 0; y < reticula.getHeight(); y = y + 1) {

				argb = reticula.getRGB(x, y);
				r = 0xff & (argb >> 16);
				g = 0xff & (argb >> 8);
				bg = 0xff & argb;

				int z = r + g + bg;

				if (z > BINA) {
					Color color1 = new Color(255, 255, 255);
					reticula.setRGB(x, y, color1.getRGB());

					colorBlanco++;
				} else {

					colorNegro++;
					Color color2 = new Color(0, 0, 0);
					reticula.setRGB(x, y, color2.getRGB());
				}
			}
			// s=s+"\n";
		}

		int t = colorNegro + colorBlanco;

		ne = (colorNegro * 100) / t;
		ba = (colorBlanco * 100) / t;
		
		int d = (int) Math.sqrt(ba);
		
		if (ba >= 80) {
			BINA = BINA + 5;
		} else {
			if (ne >= 20) {
				BINA = BINA - 5;
			}
		}
	
		 count++;
		
//			System.out.println("Negro =" + ne + "%   " + "Blanco =" + ba + "%"
//			+ "  " + BINA+"  "+d);

		
		} while (count<15);
	
		return reticula;

	}
	
	public void actionPerformed(ActionEvent e) {
		JComponent c = (JComponent) e.getSource();

		System.out.println("adlkjfldf");
			}
		
	
	
	public static void inicializaRed() {

		nn = new neuralNetwork(400, 100, 3, FICHERO_PATRONES);
		nn.setCoficienteAprendizaje((float) 0.1);
		nn.weight.loadWeight(PATH_PESOS,FICHERO_PESOS);

	}
	
	public Test() {
   	
   		
   		PintarImagen foto;
   		foto = new PintarImagen();
   	//	getContentPane().setLayout(null);
   		add(foto);
   		
   	//	getContentPane().add(foto);
   		
   		setSize(500, 500);

		setLocationRelativeTo(null);

		setResizable(false);
		setVisible(true);
		getContentPane().repaint();
		
		
	     this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {
				//	playerclose();
				System.exit(0);
			   }
	 	  });
  	   
  		foto.addMouseListener(new java.awt.event.MouseAdapter() {

  			@Override
  			public void mousePressed(MouseEvent e) {
  				mousePressed(e);
  			}
  		});

  		foto.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {

  			@Override
  			public void mouseDragged(MouseEvent e) {
  				mouseDragged(e);
  			}
  		});
        
	}
	
	class PintarImagen extends Canvas {

	    /**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		Image iFoto;

	    public void paint (Graphics g) {	
	    
		if (imagenFoto != null)
		    g.drawImage(imagenFoto, 0, 0, this);

	    }
	}
	
	public static String[] recupera_ficheros( String path) {
	
		File directorio = new File(path);
		String [] ficheros = directorio.list();
		return (ficheros);
	
	}
	
    public static void main(String[] args) {
    	
    	
    	inicializaRed();
    	
    	//String path="/Volumes/programacion/fotos/fotos/port 06/DSC01155.JPG";
    	String path="/Volumes/programacion/fotos/fotos/port 06/";
        String imagenes[] = new String[0];
        
        imagenes=recupera_ficheros(path);
        
        CanvasFrame frame = new CanvasFrame("Some Title");
        frame.setCanvasSize(500, 300);
        
      for (int x = 1; x < imagenes.length; x++) {
        	
        	
        	String rutaimagen="/Volumes/programacion/fotos/fotos/port 06/"+imagenes[x];
        	IplImage cv_image = cvLoadImage(rutaimagen, 1);
        	grayImage    = IplImage.create(cv_image.width, cv_image.height, IPL_DEPTH_8U, 1);
        	
        	cvCvtColor(cv_image, grayImage, CV_BGR2GRAY);
            cvSmooth(grayImage, grayImage, CV_BLUR, 3, 0, 0, 0);

             
            String cascadeName =  "/Users/sami/opencv/opencv/data/haarcascades/haarcascade_frontalface_default.xml";
                    
             
           CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad(cascadeName));
            
           CvMemStorage storage = CvMemStorage.create();
          
            CvSeq faces = cvHaarDetectObjects(grayImage, cascade, storage, 1.1, 10, 0);
            
            BufferedImage   g1 = null ;
           
            cvThreshold(grayImage, grayImage, 60, 255, CV_THRESH_BINARY);
            
        	System.out.println(imagenes[x]+"  caras ->"+faces.total);
        	cvSaveImage("/tmp.jpg", grayImage);
        	 
            for (int i = 0; i < faces.total; i++) {
                CvRect r = new CvRect(cvGetSeqElem(faces, i));
                
                cvRectangle(grayImage, cvPoint(r.x, r.y), cvPoint(r.x+r.width, r.y+r.height), CvScalar.RED, 5, CV_AA, 0);
               
                CvArr tmp = IplImage.create(cv_image.width, cv_image.height, IPL_DEPTH_8U, 1);
               
                imagen = loadImage("/tmp.jpg");
                g1 = toBufferedImage(imagen);
                
                cvMatchTemplate(cv_image, grayImage, tmp, CV_TM_SQDIFF_NORMED);
                
                BufferedImage imagenResultado = imagenFoto;
                
                imagenFoto = scaleToSize(200, 200, g1);
                
          
                g1 = g1.getSubimage(r.x+10 , r.y,r.width-30, r.height-10);
                g1 = scaleToSize(20, 20, g1);
                
              //  g1 = binariza(g1);
              
                
            	dmi = new downloadMosaicImage(g1, ANCHO_REJILLA, ALTO_REJILLA);
        		String s = dmi.imagenString;
        		String resultado = nn.pruebaRedModelo(s);
        		
        		System.out.println(s+"------>"+resultado);
        		//s=s+"0;1;1;";
        		
        		//if ( "011".equals(resultado) ){   		
        			
        			    frame.setTitle(imagenes[x]+"  caras ->"+faces.total);
                    	frame.showImage(grayImage);
                    	frame.pack();
                    	
        		//		salvarImagen(imagenResultado,"/Volumes/programacion/resultado/xx","png");
        		//}

;               
		//		g1 = g1.getSubimage(r.x, r.y,r.width,r.height - 10);

            }
          //  OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
            
           //   Test t = new Test();
            
//            CanvasFrame frame = new CanvasFrame("Some Title");
//            frame.setCanvasSize(500, 300);
//            frame.showImage(grayImage);
//            frame.pack();
            
     
            // ...
        }
        
        
    }
}
